package movgen;

import com.alonsoruibal.chess.bitboard.BishopMagic;
import com.alonsoruibal.chess.bitboard.RookMagic;

import state.GameState;

public class Movegen {
	
	 public static final long  darkSquares=6172840429334713770L;
	 public static final long  lightSquares=~darkSquares;
	 
	 public static final long  RANK8 =0xFF00000000000000L;
	 public static final long  RANK7= 0x00FF000000000000L;
	 public static final long  RANK6 =0x0000FF0000000000L;
	 public static final long  RANK5 =0x000000FF00000000L;
	 public static final long  RANK4= 0x00000000FF000000L;
	 public static final long  RANK3= 0x0000000000FF0000L;
	 public static final long  RANK2= 0x000000000000FF00L;
	 public static final long  RANK1= 0x00000000000000FFL;

	 public static final long  fileA =0x8080808080808080L;
	 public static final long  fileB= 0x4040404040404040L;
	 public static final long  fileC =0x2020202020202020L;
	 public static final long  fileD= 0x1010101010101010L;
	 public static final long  fileE= 0x0808080808080808L;
	 public static final long  fileF =0x0404040404040404L;
	 public static final long  fileG =0x0202020202020202L;
	 public static final long  fileH =0x0101010101010101L;
	
	 public static final long KINGSIDE=  fileF | fileG | fileH;
	 public static final long QUEENSIDE= fileA | fileB | fileC;
	
	    public static final int EP_SHIFT = 25; 
	    public static final int EP_CLEAR = 0x1FFFFFF;
		
		public static final int TO_SHIFT = 6; // Number of bits to shift to get the to-index
		public static final int PIECE_SHIFT = 12; // To get the piece moving
		public static final int CAPTURE_SHIFT = 16; // To get the capture
		public static final int TYPE_SHIFT = 20; // To the move type
		public static final int ORDERING_SHIFT = 25; // To get the ordering value
		
		
		public static final int SQUARE_MASK = 63; // 6 bits, masks out the rest of the int when it has been shifted so we only get the information we need
		public static final int PIECE_MASK  = 15; // 4 bits
		public static final int TYPE_MASK = 31; // 5 bits
		public static final int ORDERING_CLEAR = 0x1FFFFFF; // = 00000001111111111111111111111111 use with & which clears the ordering value
	
	    public static long[] knightMoveArray= new long[64];
	     public static long[] kingMoveArray= new long[64];
	    
	     public static long[][] pawnCheckArray=new long[2][64];    //white, black
	  
	    private static long knightMoves (long b)
		{
		        long c = b;
		        b ^= c;
		        b |= (c >>> 17) & 0x7F7F7F7F7F7F7F7FL;
		        b |= (c << 15) & 0x7F7F7F7F7F7F7F7FL;
		        b |= (c >>> 15) & 0xFEFEFEFEFEFEFEFEL;
		        b |= (c << 17) & 0xFEFEFEFEFEFEFEFEL;
		        b |= (c >>> 10) & 0x3F3F3F3F3F3F3F3FL;
		        b |= (c <<  6) & 0x3F3F3F3F3F3F3F3FL;
		        b |= (c >>>  6) & 0xFCFCFCFCFCFCFCFCL;
		        b |= (c << 10) & 0xFCFCFCFCFCFCFCFCL;
		        return b;
		}
		
	    private static long getWhitePawnCheckAttack(long king) {
	    	long c = ((king & ~Movegen.fileA) >>> 7 );
			long d = ((king & ~Movegen.fileH) >>> 9 );
			return  c | d ;
	    }
	    private static long getBlackPawnCheckAttack(long king) {
	    	long c = ((king & ~ Movegen.fileH ) << 7);   //capture
			long d = ((king  & ~Movegen.fileA)  << 9 );  //capture
			return  c | d ;
	    }
		 static long kingAttacks (long b)
		{
		        long c = b;
		        b |= (b >>> 1) & 0x7F7F7F7F7F7F7F7FL;
		        b |= (b << 1) & 0xFEFEFEFEFEFEFEFEL;
		        b |=  b << 8;
		        b |=  b >>> 8;
		        return b ^ c;
		}
		 
	    static {
	    	long x = 1L;
	    	for (int i=0; i < 64; i++) {
	    		knightMoveArray[i]=knightMoves(x);
	    		kingMoveArray[i]=kingAttacks(x);
	    
	    		pawnCheckArray[0][i]=getWhitePawnCheckAttack(x);
	    		pawnCheckArray[1][i]=getBlackPawnCheckAttack(x);
	    		
	    		x= x << 1;
	    	}
	    	
	    }
	    
	 private static final int noVictim=0;
	 private static final int DEFAULT_SORT_VAL=62;
	    
	 public static  int  getQueenCaptures(int cnt, int[] moves, long queens, long all,  long hisPieces, int fromType, int[] board) 
		{
		    int victim=-1,  squareTo,move, newFrom,newTo, orderValue;
		    
			int idx = Long.numberOfTrailingZeros(queens);
			long attacks;
			while (idx < 64)
			{
				newFrom=63-idx;
				attacks = BishopMagic.getBishopAttacks(idx, all) & hisPieces;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					newTo= 63-squareTo;
	    			victim= board[newTo];
	    			if (victim > 9 || victim < 0) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
	    			orderValue = sortVal[QUEEN][victim/2];
	    			move = 0
	    				    | newFrom	// from
	    					| (newTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (Move2.captureNoPromotion << TYPE_SHIFT) // move type
	    			        | (orderValue << ORDERING_SHIFT); // ordering value
	    			
	    			moves[cnt++]=move;
	    			attacks = attacks & ( attacks - 1 );
	    		}
				attacks = RookMagic.getRookAttacks(idx, all) & hisPieces;
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					newTo= 63-squareTo;
	    			victim= board[newTo];
	    			if (victim > 9 || victim < 0){
						attacks = attacks & ( attacks - 1 );
						continue;
					}
	    			orderValue = sortVal[QUEEN][victim/2];
	    			move = 0
	    				    | newFrom	// from
	    					| (newTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (Move2.captureNoPromotion << TYPE_SHIFT) // move type
	    			        | (orderValue << ORDERING_SHIFT); // ordering value
	    				
	    			moves[cnt++]=move;
	    			attacks = attacks & ( attacks - 1 );
	    		}
				queens = queens & ( queens - 1 );
				idx = Long.numberOfTrailingZeros(queens);
			} 
			return cnt;
		}
	 public static  int  getQueenNonCaptures(int cnt, int[] moves, long queens, long all, long target, int fromType)  {
		  int victim=-1,  orderValue, squareTo,move, moveType,newFrom,newTo;
			int idx = Long.numberOfTrailingZeros(queens);
			
			long attacks;
			victim=noVictim;
			moveType=Move2.simple;
			orderValue=DEFAULT_SORT_VAL;
			
			while (idx < 64){
				newFrom=63-idx;
				attacks = BishopMagic.getBishopAttacks(idx, all) & target;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					newTo= 63-squareTo;
				
					move = 0
	    				    | newFrom	// from
	    					| (newTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				attacks = RookMagic.getRookAttacks(idx, all) & target;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					newTo= 63-squareTo;
					move = 0
	    				    | newFrom	// from
	    					| (newTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				queens = queens & ( queens - 1 );
				idx = Long.numberOfTrailingZeros(queens);
			} 
			return cnt;
	 }
	
	 public static  int  getMovesForAllQueens(int cnt, int[] moves, long queens, long all, long myPieces, int fromType, int[] board) 
		{
		    int victim=-1,  orderValue, squareTo,move, moveType,newFrom,newTo;
			int idx = Long.numberOfTrailingZeros(queens);
			long notMyPieces=~myPieces;
			long attacks;
			while (idx < 64){
				newFrom=63-idx;
				attacks = BishopMagic.getBishopAttacks(idx, all) & notMyPieces;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					newTo= 63-squareTo;
					victim= board[newTo];
					if (victim > 9) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
					if (victim != -1) {
						moveType=Move2.captureNoPromotion;
						orderValue = sortVal[QUEEN][victim/2];
					}
					else {
						victim=noVictim;
						moveType=Move2.simple;
						orderValue=DEFAULT_SORT_VAL;
					}
					
					move = 0
	    				    | newFrom	// from
	    					| (newTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				attacks = RookMagic.getRookAttacks(idx, all) & notMyPieces;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					newTo= 63-squareTo;
					victim= board[63-squareTo];
					if (victim > 9) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
					if (victim != -1) {
						moveType=Move2.captureNoPromotion;
						orderValue = sortVal[QUEEN][victim/2];
					}
					else {
						victim=noVictim;
						moveType=Move2.simple;
						orderValue=DEFAULT_SORT_VAL;
					}
				
					move = 0
	    				    | newFrom	// from
	    					| (newTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				queens = queens & ( queens - 1 );
				idx = Long.numberOfTrailingZeros(queens);
			} 
			return cnt;
		}
	 public static  int getRookCaptures(int cnt, int[] moves,  long rooks, long all, long hisPieces, int fromType, int[] board) 
		{
		    int victim=-1, squareTo,move, orderValue; 
		    long attacks;
			int idx = Long.numberOfTrailingZeros(rooks);
			while (idx < 64)
			{
				attacks = RookMagic.getRookAttacks(idx, all) & hisPieces;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
	    			victim= board[63-squareTo];
	    			if (victim > 9 || victim < 0) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
	    			orderValue = sortVal[ROOK][victim/2];

	    			move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (Move2.captureNoPromotion << TYPE_SHIFT) // move type
	    			        | (orderValue << ORDERING_SHIFT); // ordering value
	    			moves[cnt++]=move;
	    			attacks = attacks & ( attacks - 1 );
	    		}
				rooks = rooks & ( rooks - 1 );
				idx = Long.numberOfTrailingZeros(rooks);
			} 
			return cnt;
		}
	 public static  int getRookNonCaptures(int cnt, int[] moves, long rooks, long all, long target, int fromType) 
		{
			
			int victim=-1, moveType, orderValue, squareTo,move;
			long attacks;
			victim=noVictim;
			moveType=Move2.simple;
			orderValue=DEFAULT_SORT_VAL;
			
			int idx = Long.numberOfTrailingZeros(rooks);
			while (idx < 64)
			{
				attacks = RookMagic.getRookAttacks(idx, all) & target;	
				
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				rooks = rooks & ( rooks - 1 );
				idx = Long.numberOfTrailingZeros(rooks);
			} 
			return cnt;
		}
	 public static  int getMovesForAllRooks(int cnt, int[] moves, long rooks, long all, long myPieces, int fromType, int[] board) 
		{
			long notMyPieces=~myPieces;
			int victim=-1, moveType, orderValue, squareTo,move;
			long attacks;
			int idx = Long.numberOfTrailingZeros(rooks);
			while (idx < 64)
			{
				attacks = RookMagic.getRookAttacks(idx, all) & notMyPieces;	
				
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					victim= board[63-squareTo];
					if (victim > 9) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
					if (victim != -1) {
						moveType=Move2.captureNoPromotion;
						orderValue = sortVal[ROOK][victim/2];
					}
					else {
						victim=noVictim;
						moveType=Move2.simple;
						orderValue=DEFAULT_SORT_VAL;
					}
					
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				rooks = rooks & ( rooks - 1 );
				idx = Long.numberOfTrailingZeros(rooks);
			} 
			return cnt;
		}
	 public static  int  getBishopCaptures(int cnt, int[] moves, long bishops, long all, long hisPieces, int fromType, int[] board) 
		{
		    int victim=-1, squareTo, move, orderValue;
			int idx = Long.numberOfTrailingZeros(bishops);
			while (idx < 64)
			{
				long attacks = BishopMagic.getBishopAttacks(idx, all) & hisPieces;	
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
	    			victim= board[63-squareTo];
	    			if (victim > 9 || victim < 0) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
	    			orderValue = sortVal[BISHOP][victim/2];
	    			move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (Move2.captureNoPromotion << TYPE_SHIFT) // move type
	    			        | (orderValue << ORDERING_SHIFT); // ordering value
	    			moves[cnt++]=move;
	    			attacks = attacks & ( attacks - 1 );
	    		}
				bishops = bishops & ( bishops - 1 );
				idx = Long.numberOfTrailingZeros(bishops);
			} 
			return cnt;
		}
	
	 public static  int  getMovesForAllBishops(int cnt, int[] moves, long bishops, long all, long myPieces, int fromType, int[] board) 
		{
			long notMyPieces=~myPieces;
			int victim=-1, moveType, orderValue, squareTo,move;
			int idx = Long.numberOfTrailingZeros(bishops);
			long attacks;
			while (idx < 64)
			{
				attacks = BishopMagic.getBishopAttacks(idx, all) & notMyPieces;	
				
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					victim= board[63-squareTo];
					if (victim > 9) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
					if (victim != -1) {
						moveType=Move2.captureNoPromotion;
						orderValue = sortVal[BISHOP][victim/2];
					}
					else {
						victim=noVictim;
						moveType=Move2.simple;
						orderValue=DEFAULT_SORT_VAL;
					}
					
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				bishops = bishops & ( bishops - 1 );
				idx = Long.numberOfTrailingZeros(bishops);
			} 
			return cnt;
		}
	 public static  int  getBishopNonCaptures(int cnt, int[] moves, long bishops, long all, long target, int fromType) 
		{
			
			int victim=-1, moveType, orderValue, squareTo,move;
			int idx = Long.numberOfTrailingZeros(bishops);
			long attacks;
			victim=noVictim;
			moveType=Move2.simple;
			orderValue=DEFAULT_SORT_VAL;
			
			while (idx < 64)
			{
				attacks = BishopMagic.getBishopAttacks(idx, all) & target;	
				
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				bishops = bishops & ( bishops - 1 );
				idx = Long.numberOfTrailingZeros(bishops);
			} 
			return cnt;
		}
	 public static int getKingCaptures(int cnt, int[] moves, long king, long hisPieces,  int fromType, int[] board) { 
		    if (king == 0) return cnt;
		    int victim=-1, squareTo, move, orderValue;
			int idx = Long.numberOfTrailingZeros(king);
			long attacks = kingMoveArray[idx] & hisPieces;
			while (attacks != 0)  {
				squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
    			victim= board[63-squareTo];
    			if (victim > 9 || victim < 0) {
					attacks = attacks & ( attacks - 1 );
					continue;
				}
    			orderValue = sortVal[KING][victim/2];
    			
    			move = 0
    				    | 63-idx	// from
    					| ( 63-squareTo << TO_SHIFT) // to
    					| (fromType  << PIECE_SHIFT) // piece moving
    					| (victim << CAPTURE_SHIFT) //piece captured 
    					| (Move2.captureNoPromotion << TYPE_SHIFT) // move type
    					| (orderValue << ORDERING_SHIFT); // ordering value
    					
    			moves[cnt++]=move;
    			attacks = attacks & ( attacks - 1 );
    		}
			return cnt;
	}
	 public static int getKingNonCaptures(int cnt, int[] moves, long king, long target,  int fromType) { 
		    if (king == 0) return cnt;
		    int victim=-1, moveType, orderValue, squareTo, move;
		    victim=noVictim;
			moveType=Move2.simple;
			orderValue=DEFAULT_SORT_VAL;
			
			int idx = Long.numberOfTrailingZeros(king);
				
			long attacks = kingMoveArray[idx] & target;
			
			while (attacks != 0)  {
				squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
				
				move = 0
 				    | 63-idx	// from
 					| ( 63-squareTo << TO_SHIFT) // to
 					| (fromType  << PIECE_SHIFT) // piece moving
 					| (victim << CAPTURE_SHIFT) //piece captured 
 					| (moveType << TYPE_SHIFT) // move type
 					| (orderValue << ORDERING_SHIFT); // ordering value
				moves[cnt++]=move;
				attacks = attacks & ( attacks - 1 );
			}
			return cnt;
	}

	    public static int getMovesForTheKing(int cnt, int[] moves, long king, long myPieces,  int fromType, int[] board) { 
			    if (king == 0) return cnt;
			    int victim=-1, moveType, orderValue, squareTo, move;
				int idx = Long.numberOfTrailingZeros(king);
					
				long attacks = kingMoveArray[idx] & (~ myPieces);
				
				while (attacks != 0)  {
					squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)]; 
					victim= board[63-squareTo];
					if (victim > 9) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
					if (victim != -1) {
						moveType=Move2.captureNoPromotion;
						orderValue = sortVal[KING][victim/2];
					}
					else {
						victim=noVictim;
						moveType=Move2.simple;
						orderValue=DEFAULT_SORT_VAL;
					}
			
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| (moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				return cnt;
		}
	   
	    public static  int getKnightCaptures(int cnt, int[] moves, long knights, long hisPieces,  int fromType, int[] board) 
		{
	    	if (knights==0) return cnt;
	    	int victim=-1, orderValue,
	    			squareTo, move;
	    	int idx = Long.numberOfTrailingZeros(knights);
	    	long attacks;
	    	while (idx < 64){
	    		
	    		attacks = knightMoveArray[idx] & hisPieces;
	    		while (attacks != 0)  {
	    			squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)];  
	    			victim= board[63-squareTo];
	    			if (victim > 9 || victim < 0) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
	    			int j = fromType/2;
					int k = victim/2;
					orderValue = sortVal[j][k];
	    			move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| ( Move2.captureNoPromotion << TYPE_SHIFT) // move type
	    			        | (orderValue << ORDERING_SHIFT); // ordering value
	    			
	    			moves[cnt++]=move;
	    			attacks = attacks & ( attacks - 1 );
	    		}
	    		knights = knights & ( knights - 1 );
	    		idx = Long.numberOfTrailingZeros(knights);
	    	} 
	    	return cnt;
		}
	    
	
	    public static  int getKnightNonCaptures(int cnt, int[] moves, long knights, long target,  int fromType) 
		{
			if (knights==0) return cnt;
			
			int victim=-1, orderValue, move;
			long attacks;
			victim=noVictim;
			
			orderValue=DEFAULT_SORT_VAL;
			
			int idx = Long.numberOfTrailingZeros(knights);
			
			
			while (idx < 64){
				attacks = knightMoveArray[idx] & target;
				 
				 while (attacks != 0)  {
					int squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)];  
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| ( Move2.simple << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				knights = knights & ( knights - 1 );
				idx = Long.numberOfTrailingZeros(knights);
			} 
			return cnt;
		}
		public static  int getMovesForAllKnights(int cnt, int[] moves, long knights, long myPieces,  int fromType, int[] board) 
		{
			if (knights==0) return cnt;
			
			int victim=-1, moveType, orderValue, move;
			long attacks;
			int idx = Long.numberOfTrailingZeros(knights);
			
			long notMyPieces=~myPieces;
			while (idx < 64){
				attacks = knightMoveArray[idx] & notMyPieces;
				 
				 while (attacks != 0)  
				 {
				
					int squareTo = magic[(int)((deBrujn*(attacks & -attacks))>>>58)];  
					victim= board[63-squareTo];
					if (victim > 9) {
						attacks = attacks & ( attacks - 1 );
						continue;
					}
					if (victim != -1) {
						moveType=Move2.captureNoPromotion;
						int j = fromType/2;
						int k = victim/2;
						orderValue = sortVal[j][k];
					}
					else {
						victim=noVictim;
						moveType=Move2.simple;
						orderValue=DEFAULT_SORT_VAL;
					}
					
					move = 0
	    				    | 63-idx	// from
	    					| ( 63-squareTo << TO_SHIFT) // to
	    					| (fromType  << PIECE_SHIFT) // piece moving
	    					| (victim << CAPTURE_SHIFT) //piece captured 
	    					| ( moveType << TYPE_SHIFT) // move type
	    					| (orderValue << ORDERING_SHIFT); // ordering value
					moves[cnt++]=move;
					attacks = attacks & ( attacks - 1 );
				}
				
				knights = knights & ( knights - 1 );
				idx = Long.numberOfTrailingZeros(knights);
			} 
			return cnt;
		}
		
		static  long deBrujn=285870213051386505L;  

		static int[] magic=new int[]  
				{ 0, 1,48, 2,57,49,28, 3,  
			61,58,50,42,38,29,17, 4,  
			62,55,59,36,53,51,43,22,  
			45,39,33,30,24,18,12, 5,  
			63,47,56,27,60,41,37,16,  
			54,35,52,21,44,32,23,11,  
			46,26,40,15,34,20,31,10,  
			25,14,19, 9,13, 8, 7, 6};  

		
		   public static final int PAWN=0;
			public static final int KNIGHT=1;
			public static final int BISHOP=2;
			public static final int ROOK=3;
			public static final int QUEEN=4;
			public static final int KING=5;
			
		
	   private static int[][] sortVal = new int[6][5];
	 //attacker, victim  0,1,2,3,4  = pawn, knight, bishop, rook, queen
		
		/*
		PxQ NxQ BxQ RxQ QxQ KxQ
		PxR NxR BxR RxR QxR KxR
		PxB NxB BxB RxB QxB KxB
		PxN NxN BxN RxN QxN KxN
		PxP NxP BxP RxP QxP KxP
		*/
	 
	
		static {
			sortVal[PAWN][PAWN]= 26;
			sortVal[PAWN][KNIGHT]= 20;
			sortVal[PAWN][BISHOP]= 14;
			sortVal[PAWN][ROOK]= 8;
			sortVal[PAWN][QUEEN]= 2;
			
			sortVal[KNIGHT][PAWN]= 27;
			sortVal[KNIGHT][KNIGHT]= 21;
			sortVal[KNIGHT][BISHOP]= 15;
			sortVal[KNIGHT][ROOK]= 9;
			sortVal[KNIGHT][QUEEN]= 3;
			
			sortVal[BISHOP][PAWN]= 28;
			sortVal[BISHOP][KNIGHT]= 22;
			sortVal[BISHOP][BISHOP]= 16;
			sortVal[BISHOP][ROOK]= 10;
			sortVal[BISHOP][QUEEN]= 4;
			
			sortVal[ROOK][PAWN]= 29;
			sortVal[ROOK][KNIGHT]= 23;
			sortVal[ROOK][BISHOP]= 17;
			sortVal[ROOK][ROOK]= 11;
			sortVal[ROOK][QUEEN]= 5;
			
			sortVal[QUEEN][PAWN]= 30;
			sortVal[QUEEN][KNIGHT]= 24;
			sortVal[QUEEN][BISHOP]= 18;
			sortVal[QUEEN][ROOK]= 12;
			sortVal[QUEEN][QUEEN]= 6;
			
			sortVal[KING][PAWN]= 31;
			sortVal[KING][KNIGHT]= 25;
			sortVal[KING][BISHOP]= 19;
			sortVal[KING][ROOK]= 13;
			sortVal[KING][QUEEN]= 7;
		}

		private static final long  circular_left_shift(long target, int shift){ 
			return target << shift |  target >>> (64-shift); 
		}
		 
		public static final int addPawnAttacks(int cnt, int[] moves, long pawns,  long enemy, int side, int pieceMoving, int flags, int[] board) {
			//just for white for the moment
			
			long attacks, ep_attacks, promotions, targets;
			//int epSquare = EnPassant.getEPSquare(flags);
			int epSquare = flags >>EP_SHIFT;
	    	final int[][] attackDiffs       = {{7, -9}, {9, -7}};
	    	final long[] promotions_mask = {RANK8, RANK1};
	    	final long[] pawnAttackFileMask     = {~fileH, ~fileA};
			// CALCULATE ATTACKS FOR LEFT, RIGHT
			for (int dir = 0; dir < 2; dir++){
				int diff =  attackDiffs[dir][side];
		
				 long x = pawns & pawnAttackFileMask[dir];
				 targets = x << diff | x >>> (64-diff); 
				
				attacks = enemy & targets;
				if (attacks != 0)
				  cnt = addPawnCaptureMoves(cnt, moves, diff, attacks & (~promotions_mask[side]),   pieceMoving,  board, Move2.captureNoPromotion);
				
			
				if ( epSquare != 0) {
					long epMask = 1L << epSquare;
					ep_attacks = targets & epMask;
					cnt = addPawnCaptureMovesEP(cnt, moves, diff, ep_attacks,  pieceMoving, side);
				}
				
				promotions = attacks & promotions_mask[side];
				if (promotions != 0)
				   cnt= addPawnCaptureMoves(cnt, moves, diff, promotions, pieceMoving,  board, Move2.capturePromotionQueen);
				
			}
			return cnt;
		}
		
		public static final int getPawnCapturesAndPromotions(int cnt, int[] moves, long pawns, long all,
				long enemy, int side, int pieceMoving, int flags, int[] board)  {
			
			final int[] pushDiffs                   = {8, -8};
			final long[] promotions_mask = {RANK8, RANK1};
			int diffs2=pushDiffs[side];
			
			long free_squares = ~all;
			long pushes=0;
			pushes = circular_left_shift(pawns, diffs2) & free_squares;
			long promotions = pushes & promotions_mask[side];
			if (promotions != 0)
				cnt=addPawnPushMoves(cnt, moves, diffs2, promotions, Move2.simplePromotionQueen,pieceMoving, 1);
			cnt=addPawnAttacks(cnt, moves, pawns, enemy, side, pieceMoving, flags,  board);
			return cnt;
		}
		
		public static final int getPawnPushes(int cnt, int[] moves, long pawns, long all, int side, int pieceMoving)  
		{
			final int[] pushDiffs                   = {8, -8};
			final long[] promotions_mask = {RANK8, RANK1};
			final long[] start_row_plus_one_mask = {RANK3,RANK6};
	        int diffs2=pushDiffs[side];
			
			long free_squares = ~all;
			
			// ADD SINGLE PUSHES
			long pushes = ( pawns << diffs2 | pawns >>> (64-diffs2)) & free_squares;
		
			long targets3=  pushes & (~promotions_mask[side]);
	
			int from, to,move, sortOrder=DEFAULT_SORT_VAL;
			while (targets3 != 0){
				to =  BitUtil.bitScanForward(targets3);
			
				from = (to - diffs2) % 64;
				
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (0 << CAPTURE_SHIFT) //piece captured 
						| ( Move2.simple << TYPE_SHIFT) // move type
						| (sortOrder << ORDERING_SHIFT); // ordering value
					
				moves[cnt++] =move;
				targets3 &= targets3 - 1;
			}
			
			long target2= pushes & start_row_plus_one_mask[side];
			long double_pushes = ( target2 << diffs2 | target2 >>> (64-diffs2)) & free_squares;
		
			sortOrder=50;
			int diffs3=2*diffs2;
			
			while (double_pushes != 0){
				to =  BitUtil.bitScanForward(double_pushes);
			
				from = (to - diffs3) % 64;
				
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (0 << CAPTURE_SHIFT) //piece captured 
						| (Move2.doublePawnMove << TYPE_SHIFT) // move type
						| (sortOrder << ORDERING_SHIFT); // ordering value
					
				moves[cnt++] =move;
				double_pushes &= double_pushes - 1;
			}
			
			return cnt;
		}
		
		public static final int getAllPawnMoves(int cnt, int[] moves, long pawns, long all,
				long enemy, int side, int pieceMoving, int flags, int[] board)  {
		
			final int[] pushDiffs                   = {8, -8};
			final long[] promotions_mask = {RANK8, RANK1};
			final long[] start_row_plus_one_mask = {RANK3,RANK6};
			
			int diffs2=pushDiffs[side];
			
			long free_squares = ~all;
			
			// ADD SINGLE PUSHES
			long pushes = ( pawns << diffs2 | pawns >>> (64-diffs2)) & free_squares;
		
			long targets3=  pushes & (~promotions_mask[side]);
	
			int from, to,move, sortOrder=DEFAULT_SORT_VAL;
			while (targets3 != 0){
				to =  BitUtil.bitScanForward(targets3);
			
				from = (to - diffs2) % 64;
				
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (0 << CAPTURE_SHIFT) //piece captured 
						| ( Move2.simple << TYPE_SHIFT) // move type
						| (sortOrder << ORDERING_SHIFT); // ordering value
					
				moves[cnt++] =move;
				targets3 &= targets3 - 1;
			}
			
			long promotions = pushes & promotions_mask[side];
			
			//cnt=addPawnPushMoves(cnt, moves, diffs2, promotions, Move2.simplePromotionQueen,pieceMoving,1);
			sortOrder=1;
			while (promotions != 0){
				to =  BitUtil.bitScanForward(promotions);
			
				from = (to - diffs2) % 64;
				
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (0 << CAPTURE_SHIFT) //piece captured 
						| ( Move2.simplePromotionQueen << TYPE_SHIFT) // move type
						| (sortOrder << ORDERING_SHIFT); // ordering value
					
				moves[cnt++] =move;
				promotions &= promotions - 1;
			}
			long target2= pushes & start_row_plus_one_mask[side];
			long double_pushes = ( target2 << diffs2 | target2 >>> (64-diffs2)) & free_squares;
		
			sortOrder=50;
			int diffs3=2*diffs2;
			
			while (double_pushes != 0){
				to =  BitUtil.bitScanForward(double_pushes);
			
				from = (to - diffs3) % 64;
				
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (0 << CAPTURE_SHIFT) //piece captured 
						| (Move2.doublePawnMove << TYPE_SHIFT) // move type
						| (sortOrder << ORDERING_SHIFT); // ordering value
					
				moves[cnt++] =move;
				double_pushes &= double_pushes - 1;
			}
			cnt=addPawnAttacks(cnt, moves, pawns, enemy, side, pieceMoving, flags,  board);
			return cnt;
		}
		
		private static int[] orderingValue= {26,26,20,20,14,14,8,8,2,2};
		
		private static final int addPawnCaptureMoves(int cnt, int[] moves, int diff, long targets, int pieceMoving, int[] board, int moveType){
			int orderValue, to, from, victim2, move;
			
			while (targets != 0){
				to =  BitUtil.bitScanForward(targets);
				from = (to - diff) % 64;
			
				victim2 = board[63 - to];
				if (victim2 < 0 || victim2 > 9) {
					targets &= targets - 1;
					continue;
				}
				orderValue=orderingValue[victim2];
			
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (victim2 << CAPTURE_SHIFT) //piece captured 
						| (moveType << TYPE_SHIFT) // move type
						| (orderValue << ORDERING_SHIFT); // ordering value
				moves[cnt++] =move;
				targets &= targets - 1;
			}
			return cnt;
		}
		
	private static final int addPawnCaptureMovesEP(int cnt, int[] moves, int diff, long targets, int pieceMoving, int side){
		    int victim2[] ={  GameState.BP, GameState.WP  };
		    int lowerbound[] = { 32, 24 };
		    int upperbound[] = { 39, 31 };
		    int from, to, move;
		    
			while (targets != 0){
				to =  BitUtil.bitScanForward(targets);
				from = (to - diff) % 64;
				
				if (( from < lowerbound[side]) || ( from > upperbound[side])) {    // we need fifth rank
					targets &= targets - 1;
					continue;
				}

				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (victim2[side] << CAPTURE_SHIFT) //piece captured 
						| (Move2.epCapture << TYPE_SHIFT) // move type
						| (26 << ORDERING_SHIFT); // ordering value
				moves[cnt++] =move;
				targets &= targets - 1;
			}
			return cnt;
		}
		
	
		private static final int addPawnPushMoves(int cnt, int[] moves, int diff, long targets,  int moveType, int pieceMoving, int sortOrder){
			int from,to,move;
			
			while (targets != 0){
				to =  BitUtil.bitScanForward(targets);
			
				from = (to - diff) % 64;
				
				move = 0
					    |  63 -from	// from
						| (63 -to << TO_SHIFT) // to
						| (pieceMoving  << PIECE_SHIFT) // piece moving
						| (0 << CAPTURE_SHIFT) //piece captured 
						| (moveType << TYPE_SHIFT) // move type
						| (sortOrder << ORDERING_SHIFT); // ordering value
					
				moves[cnt++] =move;
				targets &= targets - 1;
			}
			return cnt;
		}

}
